﻿using JESAI.DistributedLock.Internal.Data;
using MySqlConnector;
using System;
using System.Data;
using System.Threading;
using System.Threading.Tasks;

namespace JESAI.DistributedLock.MySql;

/// <summary>
/// MySql数据库连接
/// </summary>
internal class MySqlDatabaseConnection : DatabaseConnection
{
    public MySqlDatabaseConnection(IDbConnection connection)
        : base(connection, isExternallyOwned: true)
    {
    }

    public MySqlDatabaseConnection(IDbTransaction transaction)
        : base(transaction, isExternallyOwned: true)
    {
    }

    public MySqlDatabaseConnection(string connectionString)
        : base(new MySqlConnection(connectionString), isExternallyOwned: false)
    {
    }

    // 这似乎只有在同一连接上多次执行语句时才有帮助（不清楚，因为文档有限）
    public override bool ShouldPrepareCommands => false;

    public override bool IsCommandCancellationException(Exception exception)
    {
        // 见 https://mysqlconnector.net/overview/command-cancellation/
        return exception is MySqlException ex && ex.ErrorCode == MySqlErrorCode.QueryInterrupted;
    }

    public override async Task SleepAsync(TimeSpan sleepTime, CancellationToken cancellationToken, Func<DatabaseCommand, CancellationToken, ValueTask<int>> executor)
    {
        using var sleepCommand = this.CreateCommand();
        sleepCommand.SetCommandText("SELECT SLEEP(@durationSeconds)");
        sleepCommand.AddParameter("durationSeconds", sleepTime.TotalSeconds);
        sleepCommand.SetTimeout(sleepTime);

        await executor(sleepCommand, cancellationToken).ConfigureAwait(false);
    }
}
